/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ictius.estructuras.implement;

import ictius.demonio.Informante;
import ictius.estructuras.Estructura;
import ictius.estructuras.Pila;
import ictius.excepciones.DesapilaException;
import ictius.excepciones.PilaExceptions;

/**
 * @version 1.0 testeado: check!
 * @author Tadeo
 */
public final class PilaArreglo extends Estructura implements Pila {
    /**
     * Arreglo donde vamos a trabajar la Pila.
     */
    private Object[] elVector;
    /**
     * El primer elemento de la Pila.
     */
    private int tope;
    /**
     * Una cantidad mínima para el funcionamiento de la Pila.
     */
    static final int CAPACIDAD_POR_DEFECTO = 10;

    /**
     * Constructor de la pila
     */
    public PilaArreglo() {
        Informante.asustar(this);
        elVector = new Object[CAPACIDAD_POR_DEFECTO];
        tope = -1;
    }

    /**
     * Inserta un nuevo elemento en la pila.
     * @param x el elemento a insertar.
     */
    @Override
    public void apilar(Object x) {
        if (tope + 1 == elVector.length) {
            duplicarVector();
        }
        elVector[++tope] = x;
    }

    /**
     * Elimina (sin devolver algo) el último elemento insertado en la pila.
     * @throws PilaExceptions 
     */
    @Override
    public void desapilar() throws DesapilaException {
        if (esVacia()) {
            throw new DesapilaException("desapilar");
        }
        tope--; //retrocede un lugar porque se ha quitado el primero
    }

    /**
     * 
     * @return el último elemento insertado en la pila.
     * @throws PilaExceptions cuando está vacía.
     */
    @Override
    public Object primerElemento() throws PilaExceptions {

        if (esVacia()) {
            throw new PilaExceptions("cima");
        }
        return elVector[tope];
    }

    /**
     * 
     * @return el último elemento de la pila y lo elimina.
     * @throws PilaExceptions 
     */
    @Override
    public Object desapila() throws DesapilaException {
        if (esVacia()) {
            throw new DesapilaException("cimaYDesapilar");
        }
        return elVector[tope--];
    }

    /**
     * Si el valor de tope es -1 regresa true.
     * @return boolean
     */
    @Override
    public boolean esVacia() {
        return tope == 0;
    }

    /**
     * Vacía por completo la Pila.
     */
    @Override
    public void vaciar() {
        tope = 0;
    }

    /**
     * Duplica el tamaño de la pila y copia los elementos a la nueva pila con el mismo nombre.
     */
    private void duplicarVector() {
        Informante.asustar("Entre en duplicarVector");
        Object[] nuevoVector;
        nuevoVector = new Object[elVector.length * 2];


        for (int i = 0; i < elVector.length; i++) {
            nuevoVector[i] = elVector[i];
        }
        try {
            elVector = nuevoVector;
        } catch (NullPointerException n) {
            System.out.println(n);
            Informante.asustar(n + "Se ha salido de lugar la cola!");
        }
    }

    @Override
    public Object ultimoElemento() throws PilaExceptions {
        
        throw new UnsupportedOperationException("Not supported yet.");
    }
}